今明兩天會介紹兩個主要技術指標:KD指標與MACD指標。
KD 指標又稱隨機指標(Stochastic Oscillator),是技術分析中的一種動量分析方法。指標通過比較收盤價格和價格的波動範圍,預測價格趨勢逆轉的時間。「隨機」一詞是指價格在一段時間內,相對於其波動範圍的位置。
KD指標融合了動量觀念、強弱指標與移動平均線。可顯示多空力量轉折,藉此找到買賣的時機。
屬於較為敏感且短期常見技術指標,並且為封閉指標(指標從0到100是屬於封閉性的;封閉性指標當碰到連續性上漲的時候 ,不管K值或D值來到相對高點或相對低點的時候會出現鈍化)。
在看盤軟體將KD指標設定在副圖後匯出,資料檔案如Day15(1).xlsx所示。我們就可以透過以下程式碼將資料檔案匯入至DataFrame資料型態中:
##### 使用2022年11月9日到2023年4月17日之日線圖資料 #####
# 載入從「好神通PLUS」輸出的Excel檔
df = pd.read_excel('Day15(1).xlsx')
# 保存K線的基本資訊(開、高、低、收、量)
df_k_line = df.drop(columns=['SMA10','MA5','MA10','K(9,3)','D(9,3)'])
# 保存價的移動平均線
df_sma = df.drop(columns=['開盤價','最高價','最低價','收盤價','成交量','MA5','MA10','K(9,3)','D(9,3)'])
# 保存KD指標
df_stoch = df.drop(columns=['開盤價','最高價','最低價','收盤價','成交量','SMA10','MA5','MA10'])
# 將KD指標由數字轉換為百分比
df_stoch['K(9,3)'] = df_stoch['K(9,3)'] * 100.0
df_stoch['D(9,3)'] = df_stoch['D(9,3)'] * 100.0
# 將K線的Columns的名稱由中文改為英文
df_k_line = df_k_line.rename(columns={'時間':'Date','開盤價':'Open','最高價':'High','最低價':'Low','收盤價':'Close','成交量':'Volume'})
# 將價的移動平均線的Columns的名稱由中文改為英文
df_sma = df_sma.rename(columns={'時間':'Date'})
# 將KD指標的Columns的名稱由中文改為英文
df_stoch = df_stoch.rename(columns={'時間':'Date'})
# 將K線的Date設為Index
df_k_line.set_index(df_k_line['Date'],inplace=True)
df_k_line = df_k_line.drop(columns=['Date'])
# 將價的移動平均線的Date設為Index
df_sma.set_index(df_sma['Date'],inplace=True)
df_sma = df_sma.drop(columns=['Date'])
# 將KD指標的Date設為Index
df_stoch.set_index(df_stoch['Date'],inplace=True)
df_stoch = df_stoch.drop(columns=['Date'])
之後將KD指標繪製於副圖,程式碼如下所示:
# 設定K線格式
mc = mpf.make_marketcolors(up='xkcd:light red', down='xkcd:almost black', inherit=True)
s = mpf.make_mpf_style(base_mpf_style='yahoo', marketcolors=mc)
# 設定移動平均線與KD指標
added_plots={
"SMA10": mpf.make_addplot(df_sma['SMA10'],width=0.6,color='xkcd:maroon'),
'K(9,3)': mpf.make_addplot(df_stoch['K(9,3)'],width=0.8,panel=1,color='xkcd:red'),
'D(9,3)': mpf.make_addplot(df_stoch['D(9,3)'],width=0.8,panel=1,color='xkcd:blue')
}
# 繪出K線圖
kwargs = dict(type='candle', style=s, figratio=(19,10), addplot=list(added_plots.values()), datetime_format='%Y-%m-%d')
mpf.plot(df_k_line,**kwargs)
程式執行結果如下:
除了讀取看盤軟體已經算好的KD指標外,我們可以把K線資料(價量資料)交由talib套件的STOCH函式計算以求得KD指標,程式碼如下所示:
from talib.abstract import *
# 當使用talib Abstract API時,DataFrame欄位名稱需為小寫
# 請參考書籍:Python:量化交易 Ta-Lib 技術指標 139個活用技巧
df_k_line_talib = df_k_line.copy()
df_k_line_talib.columns=[ i.lower() for i in df_k_line_talib.columns]
talib_kd = STOCH( df_k_line_talib, fastk_period=9, slowk_period=3, slowd_period=3)
然後將計算好的KD指標繪製於副圖,程式碼如下所示:
# 設定K線格式
mc = mpf.make_marketcolors(up='xkcd:light red', down='xkcd:almost black', inherit=True)
s = mpf.make_mpf_style(base_mpf_style='yahoo', marketcolors=mc)
# 設定移動平均線與KD指標
added_plots={
"SMA10": mpf.make_addplot(df_sma['SMA10'],width=0.6,color='xkcd:maroon'),
'K': mpf.make_addplot(talib_kd['slowk'],width=0.8,panel=1,color='xkcd:red'),
'D': mpf.make_addplot(talib_kd['slowd'],width=0.8,panel=1,color='xkcd:blue')
}
# 繪出K線圖
kwargs = dict(type='candle', style=s, figratio=(19,10), addplot=list(added_plots.values()), datetime_format='%Y-%m-%d')
mpf.plot(df_k_line,**kwargs)
程式執行結果如下:
對比一下從看盤軟體過來資料的KD指標副圖與talib套件的STOCH函式計算的KD指標副圖,應該會發現兩者除前面資料有無外於其它地方也有差異(用程式比對會發現兩者的數值完全不同)。這是因為看盤軟體是股票一上市與上櫃就開始計算,而talib套件的STOCH函式只計算我們所取的這段區間。原因在於KD指標是滾動式的計算,要計算準確必須輸入較長時間的資料;也因此就造成兩者間有這樣的差距,而在Day16的MACD指標也會發生同樣的情形。 因此接下來的程式實作還是會使用看盤軟體的資料。
以下為KD指標現象:
KD指標中以50為分界,當KD值在50以上,視為多頭/強勢,KD值在50以下視為空頭/弱勢。KD值在80以上為超買區,表示短線過度樂觀。KD值在20以下為超賣區,表示短線過度悲觀。
KD雙線交叉往上,稱為黃金交叉,是買點。KD雙線交叉往下,稱為死亡交叉,是賣點。(K值比較快(快線),D值比較慢(慢線);當K值在上而D值在下為黃金交叉,當K值在下而D值在上為死亡交叉)
當遇到在短天期盤整時,用KD指標來買賣會失靈;也對應至股市名言:「多頭做多,空頭作空,盤整不做」。也呼應Day1開頭所說的單純使用黃金交叉與死亡交叉的策略在盤整情況有可能會產生很多無效的買賣訊號。
用以下程式碼進行黃金交叉與死亡交叉的判斷:
# 黃金交叉
def crossover(over,down):
a1 = over
b1 = down
a2 = a1.shift(1)
b2 = b1.shift(1)
crossover = (a1>a2) & (a1>b1) & (b2>a2)
return crossover
# 死亡交叉
def crossunder(down,over):
a1 = down
b1 = over
a2 = a1.shift(1)
b2 = b1.shift(1)
crossdown = (a1<a2) & (a1<b1) & (b2<a2)
return crossdown
找出黃金交叉的程式執行結果:
找出死亡交叉的程式執行結果:
當KD值到80~100之間,或0~20之間,稱之為鈍化區。KD指標在鈍化時,用來買賣會失靈。
股價創新低,但KD指標沒有創新低;股價創新高,但KD指標沒有創新高。這是一種超漲或是超跌現象,之後容易伴隨「多空反轉」。
背離現象會被歸類到「主觀性質」,主因在於需要於K線圖上找轉折點(關於轉折點的內容請參照Day9)。因此接下來將會使用Day1所提的「主觀性質客觀化」的方式一(將在看盤軟體繪製的圖形與線段以人工方式轉換成數據)把KD指標背離現象轉換為客觀數據。
先實作高檔背離。首先找出股價(K線圖)的轉折點,接著再找出KD指標死亡交叉的點。以人工方式選擇兩個轉折高點(峰位對峰位)連成直線且該直線向上傾斜,然後再選擇KD指標死亡交叉的兩個點連成直線且該直線向下傾斜。程式碼如下所示:
# 尋找轉折點
_,_,max_min = myutils.FindingTurningPoints(df_k_line,'high_low')
# 人工方式設定轉折點
turning_point_line_start_date = max_min.loc[8]['Date'].strftime('%Y-%m-%d')
turning_point_line_start_price = max_min.loc[8]['Price']
turning_point_line_end_date = max_min.loc[28]['Date'].strftime('%Y-%m-%d')
turning_point_line_end_price = max_min.loc[28]['Price']
# 尋找死亡交叉
ret_under=crossunder(df_stoch['K(9,3)'],df_stoch['D(9,3)'])
death_points = []
for idx in range(0,len(ret_under)) :
if ret_under[idx] :
death_point_date = df_stoch.iloc[idx].name
death_points.append((date_to_index(df_stoch,death_point_date),death_point_date.strftime('%Y-%m-%d'),df_stoch['D(9,3)'][idx]))
# 人工方式設定交叉點
death_point_line_x = [death_points[1][0],death_points[5][0]]
death_point_line_y = [death_points[1][2],death_points[5][2]]
slope,intercept = np.polyfit(death_point_line_x,death_point_line_y,1)
death_point_line_len = len(np.array(df_stoch['D(9,3)']))
death_point_line = np.array([np.nan]*death_point_line_len)
for idx in range(0,death_point_line_len) :
if idx >= death_point_line_x[0] and idx <= death_point_line_x[1] :
death_point_line[idx] = slope * idx + intercept
程式執行結果於下:
再下來實作低檔背離。首先找出股價(K線圖)的轉折點,再找出KD指標黃金交叉的點。以人工方式選擇兩個轉折低點(谷底對谷底)連成直線且該直線向下傾斜,然後再選擇出KD指標黃金交叉的兩個點連成直線且該直線向上傾斜。程式碼如下所示:
# 尋找轉折點
_,_,max_min = myutils.FindingTurningPoints(df_k_line,'high_low')
# 人工方式設定轉折點
turning_point_line_start_date = max_min.loc[12]['Date'].strftime('%Y-%m-%d')
turning_point_line_start_price = max_min.loc[12]['Price']
turning_point_line_end_date = max_min.loc[20]['Date'].strftime('%Y-%m-%d')
turning_point_line_end_price = max_min.loc[20]['Price']
# 尋找黃金交叉
ret_over=crossover(df_stoch['K(9,3)'],df_stoch['D(9,3)'])
golden_points = []
for idx in range(0,len(ret_over)) :
if ret_over[idx] :
golden_point_date = df_stoch.iloc[idx].name
golden_points.append((date_to_index(df_stoch,golden_point_date),golden_point_date.strftime('%Y-%m-%d'),df_stoch['D(9,3)'][idx]))
# 人工方式設定交叉點
golden_point_line_x = [golden_points[0][0],golden_points[1][0]]
golden_point_line_y = [golden_points[0][2],golden_points[1][2]]
slope,intercept = np.polyfit(golden_point_line_x,golden_point_line_y,1)
golden_point_line_len = len(np.array(df_stoch['D(9,3)']))
golden_point_line = np.array([np.nan]*golden_point_line_len)
for idx in range(0,golden_point_line_len) :
if idx >= golden_point_line_x[0] and idx <= golden_point_line_x[1] :
golden_point_line[idx] = slope * idx + intercept
程式執行結果於下:
詳細程式碼請參照「第十五天:KD指標.ipynb」。